package com.tianyu.inspection.entity.model;

import com.tianyu.inspection.common.Constants;
import com.tianyu.inspection.entity.HighConsequenceAreas;
import com.tianyu.inspection.entity.vo.ServiceRo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ui.ModelMap;

import java.lang.reflect.Field;
import java.util.Objects;

/**********************************
 * @Author YSW
 * @Description 请求实体模型
 * @Date 2021/1/11 - 17:18
 **********************************/

@Slf4j
@Data
@EqualsAndHashCode(callSuper = false)
public class OperateMo extends ModelMap {

    /**
     * 筛选字段
     */
    private ModelMap eqMap;

    /**
     * 实体新增/更新模板
     */
    private ModelMap entity;

    /**
     * SET 各字段数据
     *
     * @param type      数据筛选字段匹配目标对象
     * @param projectId 项目ID，筛选字段默认匹配
     * @param <T>       目标对象类型
     */
    public <T> ServiceRo createBuild(Class<T> type, Integer projectId) {
        entity = new ModelMap();
        final ServiceRo serviceRo = new ServiceRo();
        this.forEach((key, value) -> {
            if (Objects.nonNull(type)) {
                Field[] declaredFields = type.getDeclaredFields();
                for (Field item : declaredFields) {
                    item.setAccessible(true);
                    if (key.equals(item.getName()) && Objects.nonNull(value) && value != "") {
                        if (paramValidate(type, item.getName(), value)) {
                            entity.put(item.getName(), value);
                        } else {
                            log.error("类型[" + type.getName() + "]对象构建,参数" + "[" + item.getName() + "]值异常");
                            serviceRo.setResult(false);
                            serviceRo.setData(item.getName());
                            serviceRo.setMessage("参数[" + item.getName() + "]值异常");
                            break;
                        }
                    }
                }
            }
        });
        if (Objects.nonNull(projectId)) {
            if (projectId != 1) {
                this.put("projectId", projectId);
                entity.put("projectId", projectId);
            }
        }
        if (Objects.nonNull(this.get("id"))) {
            entity.remove("id");
        }
        if (Objects.nonNull(this.get("state"))) {
            entity.remove("state");
        }
        if (Objects.nonNull(this.get("createTime"))) {
            entity.remove("createTime");
        }
        if (Objects.nonNull(this.get("updateTime"))) {
            entity.remove("updateTime");
        }
        log.debug(this.toString());
        return serviceRo;
    }

    /**
     * SET 各字段数据
     *
     * @param type      数据筛选字段匹配目标对象
     * @param projectId 项目ID，筛选字段默认匹配
     * @param <T>       目标对象类型
     */
    public <T> ServiceRo updateBuild(Class<T> type, Integer projectId) {
        final ServiceRo serviceRo = new ServiceRo();
        eqMap = new ModelMap();
        entity = new ModelMap();
        this.forEach((key, value) -> {
            if (Objects.nonNull(type)) {
                Field[] declaredFields = type.getDeclaredFields();
                for (Field item : declaredFields) {
                    item.setAccessible(true);
                    if (key.equals(item.getName()) && Objects.nonNull(value)) {
                        if (paramValidate(type, item.getName(), value)) {
                            entity.put(item.getName(), value);
                        } else {
                            log.error("类型[" + type.getName() + "]对象构建,参数" + "[" + item.getName() + "]值异常");
                            serviceRo.setResult(false);
                            serviceRo.setData(item.getName());
                            serviceRo.setMessage("参数[" + item.getName() + "]值异常");
                            break;
                        }
                    }
                }
            }
        });
        if (Objects.nonNull(projectId)) {
            if (projectId != 1) {
                this.put("projectId", projectId);
                eqMap.put("state", 0);
                eqMap.put("project_id", projectId);
                if (Objects.nonNull(this.get("state"))) {
                    entity.remove("state");
                }
            } else {
                eqMap.put("project_id", this.get("projectId"));
            }
            entity.remove("projectId");
        }
        if (Objects.nonNull(this.get("id"))) {
            this.put("id", this.get("id"));
            eqMap.put("id", this.get("id"));
            entity.remove("id");
        }
        if (Objects.nonNull(this.get("createTime"))) {
            entity.remove("createTime");
        }
        log.debug(this.toString());
        return serviceRo;
    }

    /**
     * 参数校验
     *
     * @param type   实体类
     * @param column 属性
     * @param value  属性值
     * @param <T>    实体类泛型
     * @return 校验结果 true 校验成功 false 校验失败
     */
    private <T> Boolean paramValidate(Class<T> type, String column, Object value) {
        try {
            String typeName = type.getDeclaredField(column).getType().getSimpleName();
            String s = value.toString();
            switch (typeName) {
                case "Integer":
                case "int": {
                    try {
                        Integer.parseInt(s);
                    } catch (Exception e) {
                        log.error(String.valueOf(e));
                        return false;
                    }
                }
                break;
                case "Long":
                case "long": {
                    try {
                        Long.parseLong(s);
                    } catch (NumberFormatException e) {
                        log.error(String.valueOf(e));
                        return false;
                    }
                }
                break;
                case "Float":
                case "float": {
                    try {
                        Float.parseFloat(s);
                    } catch (NumberFormatException e) {
                        log.error(String.valueOf(e));
                        return false;
                    }
                }
                break;
                case "Double":
                case "double": {
                    try {
                        Double.parseDouble(s);
                    } catch (NumberFormatException e) {
                        log.error(String.valueOf(e));
                        return false;
                    }
                }
                break;
                case "Date": {
                    if ((!Constants.NUMBER_PATTERN.matcher(s).matches()) || s.length() > 13) {
                        return false;
                    }
                }
                break;
                case "String": {
                    if (s.contains("<") || s.contains(">")) {
                        return false;
                    }
                    if (type == HighConsequenceAreas.class && "polygonPoints".equals(column)) {
                        return s.length() <= 65535;
                    } else {
                        return s.length() <= 255;
                    }
                }
                default: {
                    return true;
                }
            }
        } catch (NoSuchFieldException e) {
            log.error(String.valueOf(e));
        }
        return true;
    }
}